package cn.mjnxin.iot.gate.connector;

import java.util.concurrent.TimeUnit;

import cn.mjnxin.iot.base.log.LogWorker;
import cn.mjnxin.iot.base.util.CommonUtil;
import cn.mjnxin.iot.gate.coder.Gate2HostEncoder;
import cn.mjnxin.iot.gate.coder.Host2GateDecoder;
import cn.mjnxin.iot.gate.handle.GateAsServer4HostInHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.UnpooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.WriteBufferWaterMark;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.timeout.IdleStateHandler;

/**
 * 网关获取终端报文
 * 
 * @author CLG 2023年10月10日
 * @version V1.0.0
 */
public class GateAsServer4Host {
    /**
     * 协议编号作为协议服务以及协议策略的唯一标识
     */
    private int serverPort;
	private int heartbeat;//心跳周期，单位分
	// 日志登记 0：无日志 1：报文长度日志 2：报文内容日志 3：所有日志
	private int logLevel;
    private EventLoopGroup boss = new NioEventLoopGroup(1);
    private EventLoopGroup work = new NioEventLoopGroup(2);

    public GateAsServer4Host(int serverPort, int heartbeat, int logLevel) {
        this.serverPort = serverPort;
        this.heartbeat = heartbeat;
        this.logLevel = logLevel;
    }

    /**
     * kernel模式
     * 
     * @return
     */
    public ServerBootstrap config() {
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        serverBootstrap.group(boss, work).channel(NioServerSocketChannel.class)
//            .option(ChannelOption.SO_KEEPALIVE, true)
//            .option(ChannelOption.TCP_NODELAY, true)
			/**
			 * 设置ByteBuf的高低水位线，原方法WRITE_BUFFER_HIGH_WATER_MARK，WRITE_BUFFER_LOW_WATER_MARK已经被废弃
			 * 由WRITE_BUFFER_WATER_MARK代替
			 * 加上WRITE_BUFFER_WATER_MARK配置后，往byteBuf写数据前需要判断iswritable
			 */
			.option(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(32 * 1024 * 1024, 64 * 1024 * 1024))
            .option(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT)
            .childOption(ChannelOption.ALLOCATOR, UnpooledByteBufAllocator.DEFAULT)
            .childOption(ChannelOption.SO_KEEPALIVE, true)
            .childOption(ChannelOption.TCP_NODELAY, true)
            .childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel sc) throws Exception {
                    // 1小时无读写事件，自动断连
                    sc.pipeline().addLast(new IdleStateHandler(heartbeat, -1, -1, TimeUnit.MINUTES));
                    // 自定义编解码器 需要在自定义的handler的前面即pipeline链的前端,不能放在自定义handler后面，否则不起作用
                    sc.pipeline().addLast("decoder", new Host2GateDecoder(logLevel));
                    sc.pipeline().addLast("encoder", new Gate2HostEncoder(logLevel));
                    sc.pipeline().addLast(new GateAsServer4HostInHandler());
                }
            });

        return serverBootstrap;
    }

    /**
     * 绑定服务到指定端口
     * 
     * @param serverBootstrap
     */
    public void bindAddress(ServerBootstrap serverBootstrap) {
        ChannelFuture channelFuture = null;
        try {
            channelFuture = serverBootstrap.bind(serverPort).sync();
            LogWorker.logForce(String.format("网关Server服务端%d已启动", serverPort));
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            LogWorker.error(e.getMessage(), e);
        } finally {
        	close();
        	if (channelFuture != null) {
                channelFuture.channel().close();
        	}
        }
    }

    /**
     * 关闭服务
     */
    public void close() {
        CommonUtil.closeEventLoop(boss, work);
    }
}
